package com.litesuits.sdk;

import android.content.Context;
import android.os.StrictMode;
import com.litesuits.android.async.AsyncTask;
import com.litesuits.android.log.Log;
import com.litesuits.common.assist.Toastor;
import com.litesuits.common.data.DataKeeper;
import com.litesuits.http.HttpConfig;
import com.litesuits.http.LiteHttp;
import com.litesuits.http.concurrent.SmartExecutor;
import com.litesuits.http.exception.handler.HttpExceptionHandler;
import com.litesuits.orm.LiteOrm;
import com.litesuits.orm.db.DataBaseConfig;
import com.litesuits.sdk.act.LiteActivity;
import com.litesuits.sdk.config.LiteConfig;
import com.litesuits.sdk.consts.LiteConst;
import com.litesuits.sdk.handler.DefaultHttpExceptionHandler;
import com.litesuits.sdk.handler.DefaultUncaughtHandler;
import com.litesuits.sdk.locator.Locator;
import com.litesuits.sdk.model.theme.Theme;

import java.util.ArrayList;

/**
 * @author MaTianyu on 2015-05-05
 */
public abstract class LiteSdk {
    protected static final String TAG = LiteSdk.class.getSimpleName();
    protected HttpExceptionHandler httpExceptionHandler;
    protected Context context;
    protected SmartExecutor smartExecutor;
    protected LiteHttp liteHttp;
    protected LiteOrm liteOrm;
    protected DataKeeper dataKeeper;
    protected Toastor toastor;
    protected Theme theme;
    protected Locator locator;
    protected static LiteSdk instance;
    protected ArrayList<LiteActivity> activityList = new ArrayList<>();

    public static synchronized LiteSdk getInstance() {
        return instance;
    }

    protected LiteSdk(Context context) {
        instance = this;
        context = context.getApplicationContext();
        // log print
        Log.isPrint = LiteConfig.debuged;

        // init handler first
        httpExceptionHandler = createHttpExceptionHandler();

        // uncaught exception
        if (LiteConfig.catchUncaughtException) {
            Thread.setDefaultUncaughtExceptionHandler(createUncaughtExceptionHandler());
        }

        // strict mode
        if (LiteConfig.strictMode) {
            setStrictMode();
        }

        // init others
        this.context = context;
        smartExecutor = createSmartExecutor();
        liteHttp = createLiteHttp();
        liteOrm = createLiteOrm();
        dataKeeper = createDataKeeper();
        locator = createLocator();
        toastor = new Toastor(context);
        theme = new Theme(Theme.WHITE);
    }

    public void addActivity(LiteActivity activity){
        activityList.add(activity);
    }

    public void removeActivity(LiteActivity activity){
        activityList.remove(activity);
    }

    public void finishAllActivity(){
        for(int i = activityList.size()-1; i >=0; i--){
            activityList.get(i).finish();
        }
        activityList.clear();
    }

    protected Locator createLocator() {
        return null;
    }

    protected void setStrictMode() {
        Log.i(TAG, "start strict mode ... ");
        StrictMode.ThreadPolicy threadPolicy = new StrictMode
                .ThreadPolicy.Builder().detectAll().penaltyLog().penaltyDropBox().build();
        StrictMode.setThreadPolicy(threadPolicy);

        StrictMode.VmPolicy vmPolicy = new StrictMode
                .VmPolicy.Builder().detectAll().penaltyLog().penaltyDropBox().build();
        StrictMode.setVmPolicy(vmPolicy);
    }

    protected Thread.UncaughtExceptionHandler createUncaughtExceptionHandler() {
        Log.i(TAG, "set uncaught handler ... ");
        return new DefaultUncaughtHandler() {

            @Override
            protected void handleException(Thread t, Throwable e) {
            }
        };
    }

    protected HttpExceptionHandler createHttpExceptionHandler() {
        return new DefaultHttpExceptionHandler(this);
    }

    protected SmartExecutor createSmartExecutor() {
        // 共享一个池
        SmartExecutor.setThreadPool(AsyncTask.mCachedSerialExecutor);
        return new SmartExecutor();
    }

    protected LiteHttp createLiteHttp() {
        LiteHttp liteHttp = LiteHttp.newApacheHttpClient(createHttpConfig());
        return liteHttp;
    }

    protected abstract HttpConfig createHttpConfig();

    protected LiteOrm createLiteOrm() {
        LiteOrm orm = LiteOrm.newSingleInstance(createDatabaseConfig());
        orm.setDebugged(LiteConfig.debuged);
        return orm;
    }

    protected abstract DataBaseConfig createDatabaseConfig();

    protected DataKeeper createDataKeeper() {
        return new DataKeeper(context, LiteConst.DEF_DATA_KEEPER_NAME);
    }

    public DefaultHttpExceptionHandler getHttpExceptionHandler() {
        return new DefaultHttpExceptionHandler(this);
    }

    public Context getContext() {
        return context;
    }

    public SmartExecutor getSmartExecutor() {
        return smartExecutor;
    }

    public LiteHttp getLiteHttp() {
        return liteHttp;
    }

    public LiteOrm getLiteOrm() {
        return liteOrm;
    }

    public DataKeeper getDataKeeper() {
        return dataKeeper;
    }

    public Toastor getToastor() {
        return toastor;
    }

    public Theme getTheme() {
        return theme;
    }

    public long getCurrentTimeMillis() {
        return System.currentTimeMillis();
    }

    public Locator getLocator() {
        return locator;
    }
}
